package com.hw.backapi.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hw.backapi.service.IClientService;
import com.hw.backapi.service.IMemberService;
import com.hw.backapi.service.IinvitorService;
import com.hw.common.contants.CommonConstants;
import com.hw.common.contants.RedisKeyContants;
import com.hw.common.enums.InvitorStatusEnum;
import com.hw.common.enums.LanguageEnum;
import com.hw.common.exception.BaseException;
import com.hw.common.utils.PhoneUtil;
import com.hw.model.entity.ClientPO;
import com.hw.model.entity.InvitorPO;
import com.hw.model.entity.MemberPO;
import com.hw.model.mapper.InvitorMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 *  邀请实现类
 * </p>
 *
 * @author 作者
 * @since 2022-11-24
 */
@Service
public class InvitorServiceImpl extends ServiceImpl<InvitorMapper, InvitorPO> implements IinvitorService {

    @Autowired
    IClientService clientServiceImpl;

    @Autowired
    IMemberService memberServiceImpl;

    @Resource
    StringRedisTemplate stringRedisTemplate;

    @Override
    public List<InvitorPO> getInvitorList(List<String> invitors,Integer status) {
        if( CollectionUtil.isEmpty(invitors) ){
            return Collections.emptyList();
        }

        LambdaQueryWrapper<InvitorPO> query = new LambdaQueryWrapper<>();
        query.in(InvitorPO::getInvitor,invitors);
        if( null != status ){
            query.eq(InvitorPO::getStatus,status);
        }

        return baseMapper.selectList(query);
    }

    @Override
    public List<InvitorPO> getInvitorListByCellphone(List<String> cellphones) {
        if( CollectionUtil.isEmpty(cellphones) ){
            return Collections.emptyList();
        }

        LambdaQueryWrapper<InvitorPO> query = new LambdaQueryWrapper<>();
        query.in(InvitorPO::getCellphone,cellphones);
        return baseMapper.selectList(query);
    }

    /**
     * @descrition 获取被邀请列表
     * @author lipeng
     * @date 2023/3/9
     * @param cellphones
     * @return java.util.List<com.hw.model.entity.InvitorPO>
     */
    public List<InvitorPO> getInvitorListByCellphone(List<String> cellphones,Long fid) {
        if( CollectionUtil.isEmpty(cellphones) ){
            return Collections.emptyList();
        }

        LambdaQueryWrapper<InvitorPO> query = new LambdaQueryWrapper<>();
        query.in(InvitorPO::getCellphone,cellphones);
        query.eq(InvitorPO::getFid,fid);
        return baseMapper.selectList(query);
    }

    /**
     * @descrition 获取邀请列表
     * @author lipeng
     * @date 2023/3/11
     * @param invitors
     * @return java.util.List<com.hw.model.entity.InvitorPO>
     */
    private List<InvitorPO> getInvitorList(String invitors) {
        if( StrUtil.isEmpty(invitors) ){
            return Collections.emptyList();
        }

        LambdaQueryWrapper<InvitorPO> query = new LambdaQueryWrapper<>();
        query.eq(InvitorPO::getInvitor,invitors);
        return baseMapper.selectList(query);
    }

    /**
     * @descrition  获取被邀请信息
     * @author lipeng
     * @date 2023/3/16
     * @param cellphone
     * @param fid
     * @return com.hw.model.entity.InvitorPO
     */
    private InvitorPO getInvitorInfo(String cellphone,Long fid) {
        LambdaQueryWrapper<InvitorPO> query = new LambdaQueryWrapper<>();
        query.eq(InvitorPO::getCellphone,cellphone);
        query.eq(InvitorPO::getFid,fid);
        query.last("limit 1");
        return baseMapper.selectOne(query);
    }

    @Override
    public void doInvitor(String cellphone, String doctorName,ClientPO clientPO) {
        cellphone = PhoneUtil.replacePhone(cellphone);
        if( clientPO.getCellphone().equals(cellphone)){
            throw new BaseException("can't invite yourself");
        }

        //邀请人是否有医院
        MemberPO memberInfo = memberServiceImpl.getMemberMasterInfo(clientPO.getId());
        if( null == memberInfo ){
            throw new BaseException("The doctor do not have his own hospital");
        }
        if( !memberInfo.getIsMaster().equals(1) ){
            throw new BaseException("The doctor do not have his own hospital , cannot invite others");
        }
        Long fid = memberInfo.getFid();

        //获取被邀请人用户信息
        List<ClientPO> clientInfoList = clientServiceImpl.getClientInfo(Collections.singletonList(cellphone));
        if( CollectionUtil.isNotEmpty(clientInfoList) ){
            ClientPO clientInfo = clientInfoList.get(0);
            //如果被邀请人不是医生
            if( !clientInfo.getIsDoctor().equals(CommonConstants.DOCTOR) ){
                throw new BaseException("the invitee is not a doctor");
            }

            //如果已经在成员中则不在增加
            MemberPO memberInvitorInfo = memberServiceImpl.getMemberInfo(fid, clientInfo.getId());
            if( null != memberInvitorInfo ){
                return;
            }
        }

        //获取邀请信息，如果已经
        InvitorPO invitorInfo = getInvitorInfo(cellphone, fid);
        if( null != invitorInfo ){
            if( invitorInfo.getStatus().equals(InvitorStatusEnum.INVITED.getCode()) || invitorInfo.getStatus().equals(InvitorStatusEnum.AGREE.getCode())  ){
                throw new BaseException("Applications cannot be sent to an authorized doctor");
            }
        }


        addInvitorBatch(fid,clientPO,Collections.singletonList(cellphone),doctorName);
    }

    /**
     * @descrition
     * @author lipeng
     * @date 2023/5/28
     * @param cellphone  被邀请手机号
     * @param clientPO 医院管理员信息
     * @return void
     */
    @Override
    public void doDelInvitor(String cellphone,ClientPO clientPO) {
        //转换手机号
        cellphone = PhoneUtil.replacePhone(cellphone);
        if( clientPO.getCellphone().equals(cellphone)){
            throw new BaseException("you cannot cancel authorization for yourself");
        }

        //获取被邀请人用户信息
        List<ClientPO> clientInfoList = clientServiceImpl.getClientInfo(Collections.singletonList(cellphone));
        if( CollectionUtil.isEmpty(clientInfoList) ){
            throw new BaseException("user does not exist");
        }

        //被邀请人
        ClientPO clientInfo = clientInfoList.get(0);
        if( !clientInfo.getIsDoctor().equals(CommonConstants.DOCTOR) ){
            throw new BaseException("can't invite yourself");
        }

        //医院人员信息
        MemberPO memberInfo = memberServiceImpl.getMemberMasterInfo(clientPO.getId());
        if( null == memberInfo ){
            throw new BaseException("The doctor do not have his own hospital");
        }
        if( !memberInfo.getIsMaster().equals(1) ){
            throw new BaseException("The doctor do not have his own hospital , cannot invite others");
        }
        Long fid = memberInfo.getFid();

        //获取被邀请人邀请信息
        InvitorPO invitorInfo = getInvitorInfo(cellphone, fid);

        //或者没有被邀请信息了如果被邀请人已同意，删除member
        if(  null == invitorInfo || InvitorStatusEnum.AGREE.getCode().equals(invitorInfo.getStatus()) ){
            MemberPO memberInvitorInfo = memberServiceImpl.getMemberInfo(fid, clientInfo.getId());
            if( null == memberInvitorInfo ){
                throw new BaseException("User member information does not exist");
            }
            memberServiceImpl.getBaseMapper().deleteById(memberInvitorInfo);
        }

        delInvitorBatch(fid,clientPO,Collections.singletonList(cellphone));
    }

    @Override
    public void doInvitor(List<String> cellphones,String doctorName, ClientPO clientPO) {
        //将cellphone +81 转换为 +810
        List<String> cellPhoneList = cellphones.stream().map(PhoneUtil::replacePhone).collect(Collectors.toList());

        //不能邀请自己
        cellPhoneList.forEach(phone -> {
            if( clientPO.getCellphone().equals(phone)){
                throw new BaseException("can't invite yourself");
            }
        });

        MemberPO memberInfo = memberServiceImpl.getMemberMasterInfo(clientPO.getId());
        if( null == memberInfo ){
            throw new BaseException("The doctor do not have his own hospital");
        }
        if( !memberInfo.getIsMaster().equals(1) ){
            throw new BaseException("The doctor do not have his own hospital , cannot invite others");
        }
        Long fid = memberInfo.getFid();

        //获取被邀请人用户信息
        List<ClientPO> clientInfoList = clientServiceImpl.getClientInfo(cellPhoneList);
        if( CollectionUtil.isNotEmpty(clientInfoList) ){

            clientInfoList.forEach(clientInfo->{
                if( !clientInfo.getIsDoctor().equals(CommonConstants.DOCTOR) ){
                    throw new BaseException("the invitee is not a doctor");
                }
                //如果已经在成员中则不在增加
                MemberPO memberInvitorInfo = memberServiceImpl.getMemberInfo(fid, clientInfo.getId());
                if( null == memberInvitorInfo ){
                    return;
                }

                cellPhoneList.remove(clientInfo.getCellphone());
//                if( !memberInfo.getIsMaster().equals(1) ){
//                    throw new BaseException("邀请失败，被邀请人isMaster不等于1");
//                }
            });
        }


        List<InvitorPO> removeList = new ArrayList<>();
        List<String> addList = new ArrayList<>();

        //获取所有的邀请，查看是否需要删除或者添加
        List<InvitorPO> invitorList = getInvitorList(clientPO.getCellphone());

        //如果为空，则所有的都需要添加
        if( CollectionUtil.isNotEmpty(invitorList) ){
            Map<String, Integer> cellphoneStatusMap = invitorList.stream().collect(Collectors.toMap(InvitorPO::getCellphone,
                    InvitorPO::getStatus));

            addList =
                    cellPhoneList.stream().filter(phone -> {
                        Integer invitorStatus = cellphoneStatusMap.get(phone);
                        if( null ==  invitorStatus){
                            return true;
                        }
                        if( invitorStatus.equals(InvitorStatusEnum.REFUSE.getCode()) ){
                            return true;
                        }
                        return false;
                    }).collect(Collectors.toList());
            //数据库里的删除所有传过来的。就是需要删除的
            removeList =
                    invitorList.stream().filter(invitor -> !cellPhoneList.contains(invitor.getCellphone())).collect(Collectors.toList());
        }else{
            addList.addAll(cellPhoneList);
        }

        addInvitorBatch(fid,clientPO,addList,doctorName);
        doDelInvitor(fid,clientPO,removeList);
    }

    /**
     * @descrition 去删除
     * @author lipeng
     * @date 2023/3/11
     * @param fid
     * @param client  邀请人
     * @param removeList 被邀请人列表
     * @return void
     */
    public void doDelInvitor(Long fid,ClientPO client,List<InvitorPO> removeList){
        if( CollectionUtil.isEmpty(removeList) ){
            return;
        }

        List<String> phones = new ArrayList<>(removeList.size());

        removeList.forEach(invitorPO -> {
            //已同意 需要删除家庭成员
            if( invitorPO.getStatus().equals(2) ){
                //获取被邀请人用户信息
                List<ClientPO> invitorClientInfoList = clientServiceImpl.getClientInfo(Collections.singletonList(invitorPO.getCellphone()));
                if( CollectionUtil.isEmpty(invitorClientInfoList) ){
                    throw new BaseException(" Error in get client");
                }
                ClientPO invitorClient = invitorClientInfoList.get(0);
                MemberPO invitorMemberInfo = memberServiceImpl.getMemberInfo(fid, invitorClient.getId());
                if( null == invitorMemberInfo ){
                    throw new BaseException("Error in get member");
                }
                memberServiceImpl.getBaseMapper().deleteById(invitorMemberInfo);
            }

            phones.add(invitorPO.getInvitor());
        });

        //移除邀请
        delInvitorBatch(fid,client,phones);

        //清除缓存
        delInvitorCache(2,client,phones);
    }

    /**
     * @descrition 批量删除邀请
     * @author lipeng
     * @date 2023/3/11
     * @param fid
     * @param client
     * @param phones
     * @return void
     */
    private void delInvitorBatch(Long fid,ClientPO client,List<String> phones){
        LambdaQueryWrapper<InvitorPO> query = new LambdaQueryWrapper<>();
        query.eq(InvitorPO::getFid,fid);
        query.in(InvitorPO::getCellphone,phones);
        this.remove(query);
    }

    /**
     * @descrition 批量添加邀请
     * @author lipeng
     * @date 2023/3/11
     * @param fid  fid
     * @param client 邀请人
     * @param phones 被邀请人
     * @return void
     */
    private void addInvitorBatch(Long fid,ClientPO client,List<String> phones ,String doctorName){
        if( CollectionUtil.isEmpty(phones) ){
            return;
        }
        List<String> finalPhones  = new ArrayList(phones);

        //查询别邀请人的邀请记录
        List<InvitorPO> invitorListByCellphone = getInvitorListByCellphone(phones,fid);
        if( CollectionUtil.isNotEmpty(invitorListByCellphone) ){

            invitorListByCellphone.forEach(invitor->{
                //如果状态已拒绝，则更新为邀请
                if( InvitorStatusEnum.REFUSE.getCode().equals(invitor.getStatus()) ){
                    invitor.setStatus(InvitorStatusEnum.INVITED.getCode());
                    this.updateById(invitor);
                }
                //用户已经同意了/更新状态为邀请的，不能在添加
                finalPhones.remove(invitor.getCellphone());
            });
        }

        List<InvitorPO> invitors = finalPhones.stream().map(phone -> {
            InvitorPO invitorPO = new InvitorPO();
            invitorPO.setFid(fid);
            invitorPO.setCellphone(phone);
            invitorPO.setHonorific(doctorName);
            invitorPO.setNotifyTimes(0);
            invitorPO.setStatus(1);
            invitorPO.setCreatedAt(new Date());
            invitorPO.setUpdatedAt(new Date());
            invitorPO.setInvitor(client.getCellphone());
            invitorPO.setType(client.getIsDoctor());
            return invitorPO;
        }).collect(Collectors.toList());

        this.saveBatch(invitors);

        delInvitorCache(1,client,phones);
    }

    /**
     * @descrition 清除缓存
     * @author lipeng
     * @date 2023/3/11
     * @param type 1add 2del
     * @param client
     * @return void
     */
    private void delInvitorCache(Integer type,ClientPO client,List<String> phones){

        if( type.equals(1) ){
            phones.forEach(phone->{
                delCache(RedisKeyContants.INVITE_SUFFIX + phone);
                delCache(RedisKeyContants.FAMILY_SUFFIX + phone);
                delCache(RedisKeyContants.FAMILY_SUFFIX + client.getCellphone());
            });
        }else{
            phones.forEach(phone->{
                delCache(RedisKeyContants.INVITE_SUFFIX + phone);
                //清除所有家庭成员数据
                delCache(RedisKeyContants.FAMILY_SUFFIX + phone);

            });
        }
    }

    /**
     * @descrition 清除缓存
     * @author lipeng
     * @date 2023/3/13
     * @param prefix 前缀
     * @return void
     */
    private void delCache(String prefix){
        for (LanguageEnum languageEnum : LanguageEnum.values()) {
            stringRedisTemplate.delete(prefix + languageEnum);
        }
    }
}
